

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct sVar {
  char nom[50];
  char type[50];
  int get; /* représente le type de passage de parametre pour la fonction get 1 = par valeur et 0 par pointeur */
};

typedef struct sVar Variable;

struct sFiche {
  char nomFichier[50];
  char nomStruct[50];
  char nomTypedef[50];
  int nbChamps;
  Variable var[50];
};

typedef struct sFiche Fiche;

void ecritureEnteteH(FILE *f, Fiche fic)
{
  char nn[50];
  int i;
  for(i = 0; fic.nomFichier[i] != '\0'; i++)
    nn[i] = toupper(fic.nomFichier[i]);
  nn[i] = '\0';

  fprintf(f, "/**\n");
  fprintf(f," * @file %s.h\n",fic.nomFichier);
  fprintf(f," * @brief Fichier d'entête du module %s.\n", fic.nomFichier);
  fprintf(f," *\n");
  fprintf(f," * @author Rachid Delory, Mamadou Keita, Florian Bernard\n");
  fprintf(f," */\n\n");
  fprintf(f,"#ifndef H_%s_H\n", nn);
  fprintf(f,"#define H_%s_H\n\n", nn);
  fprintf(f,"/* *********************************************************************\n\n");
  fprintf(f,"                       Librairies de %s                           \n\n", fic.nomFichier);
  fprintf(f,"********************************************************************* */\n\n");
  fprintf(f,"#include <stdlib.h>\n#include <stdio.h>\n#include <stddef.h>\n\n");
  fprintf(f,"/* *********************************************************************\n\n");
  fprintf(f,"                        Définitions de types                           \n\n");
  fprintf(f,"********************************************************************* */\n\n");

}

void ecritureEnteteC(FILE *f, Fiche fic)
{
  char nn[50];
  int i;
  for(i = 0; fic.nomFichier[i] != '\0'; i++)
    nn[i] = toupper(fic.nomFichier[i]);
  nn[i] = '\0';

  fprintf(f, "/**\n");
  fprintf(f," * @file %s.c\n",fic.nomFichier);
  fprintf(f," * @brief Fichier source du module %s.\n", fic.nomFichier);
  fprintf(f," *\n");
  fprintf(f," * @author Rachid Delory, Mamadou Keita, Florian Bernard\n");
  fprintf(f," */\n\n");
  fprintf(f,"#ifndef H_%s_H\n", nn);
  fprintf(f,"#define H_%s_H\n\n", nn);
  fprintf(f,"/* *********************************************************************\n\n");
  fprintf(f,"                       Librairies de %s                          \n\n", fic.nomFichier);
  fprintf(f,"********************************************************************* */\n\n");
  fprintf(f,"#include \"%s.h\"\n\n", fic.nomFichier);
  fprintf(f,"/* *********************************************************************\n\n");
  fprintf(f,"                        Fonctions                                      \n\n");
  fprintf(f,"********************************************************************* */\n\n");
}
void ecritureStructH(FILE *f, Fiche fic)
{
  int i;
  fprintf(f,"/**\n");
  fprintf(f," * @struct %s\n", fic.nomStruct);
  fprintf(f," * @brief Structure utilisée pour la gestion des %s\n", fic.nomTypedef);
  fprintf(f," *\n");
  fprintf(f," * Cette structure est utilisée pour gérer un %s. Les champs de cette structure doivent être modifiés ou lus par les accesseurs et mutateurs. Ils doivent être initialisés et libérés avec les fonctions prévus à cette effet\n", fic.nomTypedef);
  fprintf(f," */\n");
  fprintf(f,"struct %s {\n", fic.nomStruct);
  for(i = 0; i < fic.nbChamps; i++)
    {
      fprintf(f,"\t%s %s; /** */\n", fic.var[i].type, fic.var[i].nom);
    }
  fprintf(f,"};\n");
  fprintf(f,"/**\n");
  fprintf(f," * @typedef %s\n", fic.nomTypedef);
  fprintf(f," * @brief Redéfinit la structure %s\n", fic.nomStruct);
  fprintf(f," */\n");
  fprintf(f,"\ttypedef struct %s %s;\n\n", fic.nomStruct, fic.nomTypedef);
}

void ecritureEnteteMuttateur(FILE *f, Fiche fic)
{
  fprintf(f,"/* *********************************************************************\n\n");
  fprintf(f,"           Accesseurs et Mutateurs de la structure %s               \n\n", fic.nomTypedef);
  fprintf(f,"********************************************************************* */\n\n");
}

void ecritureMuttateur(FILE *fH, FILE *fC, Fiche fic, char *nom)
{
  int i;
  for(i = 0; i < fic.nbChamps; i++)
    {
      char nomV[50];
      strcpy(nomV, fic.var[i].nom);
      nomV[0] = toupper(nomV[0]);

      fprintf(fH,"/**\n");
      fprintf(fH," * @fn %s get%s%s(const %s ", fic.var[i].type, nomV, nom, fic.nomTypedef);
      if(fic.var[i].get == 1)
	fprintf(fH, "* ptr) ;\n");
      else
	fprintf(fH, " ptr) ;\n");

      fprintf(fH," * @brief \n");
      fprintf(fH," *\n");
      fprintf(fH," * @param ptr pointeur vers %s\n", fic.nomTypedef);
      fprintf(fH," * @return %s\n", fic.var[i].type);
      fprintf(fH," */\n");
      fprintf(fH,"%s get%s%s(const %s ", fic.var[i].type, nomV, nom, fic.nomTypedef);
      if(fic.var[i].get == 1)
	fprintf(fH, "* ptr) ;\n\n");
      else
	fprintf(fH, " ptr) ;\n\n");

      fprintf(fC,"%s get%s%s(const %s ", fic.var[i].type, nomV, nom, fic.nomTypedef);
      if(fic.var[i].get == 1)
	fprintf(fC, "* ptr)\n{");
      else
	fprintf(fC, " ptr)\n{");
      fprintf(fC, "\n\treturn ptr");
      if(fic.var[i].get == 1)
	fprintf(fC, "->");
      else
	fprintf(fC, ".");
      fprintf(fC,"%s;\n}\n\n", fic.var[i].nom);

      fprintf(fH,"/**\n");
      fprintf(fH," * @fn void set%s%s(", nomV, nom);
      fprintf(fH,"%s *ptr, const %s val) ;\n", fic.nomTypedef, fic.var[i].type);
      fprintf(fH," * @brief Modifie .\n");
      fprintf(fH," *\n");
      fprintf(fH," * @param[in,out] ptr Pointeur vers %s.\n", fic.nomTypedef);
      fprintf(fH," * @param val.\n");
      fprintf(fH," */\n");
      fprintf(fH,"void set%s%s(", nomV, nom);
      fprintf(fH,"%s *ptr, const %s val) ;\n\n", fic.nomTypedef, fic.var[i].type);

      fprintf(fC,"void set%s%s(", nomV, nom);
      fprintf(fC,"%s *ptr, const %s val)\n{\n\t", fic.nomTypedef, fic.var[i].type);
      fprintf(fC,"ptr->%s = val;\n}\n\n", fic.var[i].nom);
    }
}

int main (int argc, char **argv)
{
  FILE *fLecture, *fH, *fC;
  int i;
  Fiche fic;

  if(argc != 2)
    {
      fprintf(stderr, "Usage fichier text contenant une structure par ligne sous la forme :\nnomFichier nomStructure nomTypedef nombreVariables nomVar1 type1 'passage par copie 0 ou par pointeur 1' var2...\n");
      return 1;
    }
  fLecture = fopen(argv[1], "r");
  if(fLecture == NULL)
    {
      fprintf(stderr, "Lecture impossible");
      exit(EXIT_FAILURE);
    }

  while(fscanf(fLecture,"%s", (fic.nomFichier)) >= 1)
    {
      char nom[50], nomEnd[5];
      printf("Fichier %s\t", fic.nomFichier);
      if(fscanf(fLecture, "%s", (fic.nomStruct)) < 1)
	 break;
      printf("Structure %s\t", fic.nomStruct);
      if(fscanf(fLecture, "%s", (fic.nomTypedef)) < 1)
	 break;
      printf("Typedef %s\t", fic.nomTypedef);
      if(fscanf(fLecture, "%d", &(fic.nbChamps)) < 1)
	 break;
      printf("Nombre de champs %d\n", fic.nbChamps);
      sprintf(nom, "%s.c", fic.nomFichier);
      printf("Creation de %s\n", nom);
      fC = fopen(nom,"w");
      sprintf(nom, "%s.h", fic.nomFichier);
      printf("Creation de %s\n", nom);
      fH = fopen(nom, "w");
      nomEnd[0] = '_';

      for(i = 1; i < 4 && fic.nomFichier[i - 1] != '\0'; i++)
	nomEnd[i] = fic.nomFichier[i - 1];
      nomEnd[i] = '\0';
      nomEnd[1] = toupper(nomEnd[1]);

      printf("Ecriture de l'entete du fichier h\n");
      ecritureEnteteH(fH, fic);
      ecritureEnteteC(fC, fic);
  
      for(i = 0; i < fic.nbChamps; i++)
	{
	  if(fscanf(fLecture, "%s", (fic.var[i].nom)) < 1)
	    break;
	  printf("champs %d nom: %s",i ,fic.var[i].nom);
	  if(fscanf(fLecture, "%s", (fic.var[i].type)) < 1)
	    break;
	  if(strstr(fic.var[i].type, "signed") != NULL)
	    {
	      char tmp[50];
	      fscanf(fLecture, "%s", tmp);
	      strcat(fic.var[i].type, " ");
	      strcat(fic.var[i].type, tmp);
	    }
	  fseek(fLecture, 1, SEEK_CUR);
	  if(fgetc(fLecture) == '*')
	    {
	      strcat(fic.var[i].type, " *");
	    }
	  else
	    fseek(fLecture, -1, SEEK_CUR);
	  printf("\ttype: %s", fic.var[i].type);
	  if(fscanf(fLecture, "%d", &(fic.var[i].get)) < 1)
	    break;
	  printf("\tget: %d", fic.var[i].get);
	}
      printf("\n");
      ecritureStructH(fH, fic);
      ecritureEnteteMuttateur(fH, fic);
      ecritureMuttateur(fH, fC, fic, nomEnd);
      fprintf(fH, "\n#endif\n");
      fclose(fH);
      fclose(fC);
    }
    return 0;
}
